
package com.studiofortress.sf.audio;

import com.studiofortress.sf.util.ArrayUtil;

/**
 *
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
class ArrayAudioBuffer implements AudioBuffer
{
    private byte[] buffer;
    private int bufferIndex;
    private boolean finished;
    
    public ArrayAudioBuffer()
    {
        this.buffer = new byte[512];
        this.bufferIndex = 0;
        this.finished = false;
    }

    public byte getByte(int location)
    {
        return buffer[location];
    }
    
    public void addBuffer(byte[] audio)
    {
        addBuffer( audio, audio.length );
    }
    
    public synchronized void addBuffer(byte[] audio, int audioLength)
    {
//System.out.println("AudioBuffer.addBuffer: length: " + audioLength);
        if (isFinished()) {
            throw new IllegalStateException("Cannot add data to an AudioBuffer that is finished.");
        }
        
        final int newBufferIndex = bufferIndex + audioLength;
        if (buffer.length < newBufferIndex) {
            final int newSize = Math.max( newBufferIndex, (buffer.length*4)/3 );
            buffer = ArrayUtil.copyOf( buffer, newSize );
        }
        
        System.arraycopy( audio, 0, buffer, bufferIndex, audioLength );
        bufferIndex = newBufferIndex;
    }
    
    public synchronized byte[] getBuffer(final int start, final int length)
    {
        final int returnBufferSize = Math.min( length, buffer.length-start );
        final byte[] returnBuffer = new byte[ returnBufferSize ];
        
        System.arraycopy( buffer, start, returnBuffer, 0, returnBufferSize );

        return returnBuffer;
    }

    /**
     * @return The number of bytes stored in this buffer.
     */
    public int size()
    {
        return bufferIndex;
    }

    /**
     * Compacts down the internal buffer so that it fits into only the number of
     * bytes used.
     */
    public synchronized void finish()
    {
        if (isFinished()) {
            throw new IllegalStateException("Finished should only be called the once.");
        }

        if (bufferIndex != buffer.length) {
            buffer = ArrayUtil.copyOf( buffer, bufferIndex );
        }

        finished = true;
    }
    
    /**
     * @return True if this buffer is finished with and no more data will be added to it.
     */
    public synchronized boolean isFinished()
    {
        return finished;
    }
}
